﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
using SchedulerControl.Adorners;
using SchedulerControl.Adorners.Frames;


namespace SchedulerControl
{
    public partial class ScheduleDayViewControl : UserControl
    {
        DispatcherTimer _timerOpen;
		DispatcherTimer _timerClose;       

        private ScheduleItemControl _currentEditingItem;
        public bool IsInEditMode { get; set; }
        private PersianCalendar calendar;
        private DateTime _currentViewDate = DateTime.Now;
        public DateTime CurrentViewDate
        {
            get { return _currentViewDate; }
            set
            {
                var monthNames = new PersianCalendar.PersianMonthNames();
                var dayNames = new PersianCalendar.PersianWeekDayNames(); 

                _currentViewDate = value;
                
            }
        }

        private List<ScheduleItemControl> scheduleItems;
        Adorner _adorner = new Adorner();
        GlassFrame frame3 = new GlassFrame();
        private AdornedObject item1;
        private AdornedObject item2;
        public ScheduleDayViewControl()
        {
            InitializeComponent();
            scheduleItems = new List<ScheduleItemControl>();
            _adorner.Width = 0;
            _adorner.Height = 0;
            cursorPlane.SetSystemCursorElement(panelDisplay);
            _adorner.SetCursor(cursorPlane);
            _adorner.SetAdornerFrame(frame3);
            _adorner.CanRotate = false;
            _adorner.Edited += new Adorner.EditHandler(_adorner_Edited);
            _adorner.Closed += new Adorner.CloseHandler(_adorner_Closed);
            _adorner.Maximized += new Adorner.MaximizeHandler(_adorner_Maximized);
            _adorner.MouseEnter += new MouseEventHandler(_adorner_MouseEnter);
            _adorner.MouseLeave += new MouseEventHandler(_adorner_MouseLeave);
            _adorner.MouseLeftButtonDown += new MouseButtonEventHandler(_adorner_MouseLeftButtonDown);
            _adorner.thumbMove.DragCompleted += new System.Windows.Controls.Primitives.DragCompletedEventHandler(thumbMove_DragCompleted);
            
            //_adorner.SetBounds(this);
            calendar = new PersianCalendar(); 
            this.panelDisplay.LayoutUpdated += new EventHandler(panelDisplay_LayoutUpdated);

            var monthNames = new PersianCalendar.PersianMonthNames();
            var dayNames = new PersianCalendar.PersianWeekDayNames(); 

            panelDisplay.Children.Add(_adorner);
            
            
			btnNewItem.Click +=new System.Windows.RoutedEventHandler(btnNewItem_Click);
            btnNewItem.MouseEnter += new MouseEventHandler(btnNewItem_MouseEnter);
            btnNewItem.MouseLeave += new MouseEventHandler(btnNewItem_MouseLeave);
            this.MouseLeave += new MouseEventHandler(ScheduleDayViewControl_MouseLeave);



            _timerOpen = new DispatcherTimer();
            _timerOpen.Interval = TimeSpan.FromMilliseconds(500);
            _timerOpen.Tick += new EventHandler(_timerOpen_Tick);

            _timerClose = new DispatcherTimer();
            _timerClose.Interval = TimeSpan.FromMilliseconds(2000);
            _timerClose.Tick += new EventHandler(_timerClose_Tick);


        }

        void thumbMove_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
        {
            if (IsInCollision((ScheduleItemControl)((AdornedObject)(_adorner.AdornedObject)).AdornedElement)) throw new Exception();
        }

        void _adorner_Clicked(object sender)
        {
            
        }

        void _adorner_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            
        }

        void _adorner_MouseLeave(object sender, MouseEventArgs e)
        {
            
        }       

        void btnNewItem_MouseLeave(object sender, MouseEventArgs e)
        {
            _timerOpen.Stop();
            _timerClose.Start(); 
        }

        void btnNewItem_MouseEnter(object sender, MouseEventArgs e)
        {
            _timerOpen.Stop();
            _timerClose.Start(); 
        }

        void _timerClose_Tick(object sender, EventArgs e)
        {
            
            btnNewItem.Visibility = System.Windows.Visibility.Collapsed;
            _timerClose.Stop();
        }

        void _timerOpen_Tick(object sender, EventArgs e)
        {
            Canvas.SetTop(btnNewItem, (double)newMouseHeight);
           
            btnNewItem.Visibility = System.Windows.Visibility.Visible;
            _timerOpen.Stop();
            _timerClose.Stop();
            _timerClose.Start(); 
        }

        void _adorner_MouseEnter(object sender, MouseEventArgs e)
        {
            btnNewItem.Visibility = System.Windows.Visibility.Collapsed;
            _timerOpen.Stop();
            _timerClose.Stop();
        }

        void ScheduleDayViewControl_MouseLeave(object sender, MouseEventArgs e)
        {
            btnNewItem.Visibility = System.Windows.Visibility.Collapsed;
            _timerOpen.Stop();
            _timerClose.Stop();
        }

       

        private decimal _currentContainerWidth = 0;
        private decimal _currentContainerHeight = 0;


        protected override Size MeasureOverride(Size availableSize)
        {
//            try
//            {
                if (!DesignerProperties.IsInDesignTool)
                {
                    foreach (ScheduleItemControl scheduleItemControl in scheduleItems)
                    {
                        AdornedObject adornedObject = (AdornedObject) scheduleItemControl.Tag;
                        adornedObject.ObjectWidth = availableSize.Width;
                    }

                    _currentContainerWidth = (decimal) availableSize.Width;
                    _currentContainerHeight = (decimal)availableSize.Height;
                    //frame3.Width = availableSize.Width;
                    _adorner.Width = availableSize.Width;
                    _adorner.SetBounds(0, 0, availableSize.Width, availableSize.Height);
                }
//            }catch
//            {
//            }
            return availableSize;
              
        }

        void panelDisplay_LayoutUpdated(object sender, EventArgs e)
        {
            double aaa = panelDisplay.ActualHeight;
            
        }

        private decimal panelDisplayHeight;
        private decimal panelDisplayWidth;
        void panelDisplay_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            decimal w = (decimal)e.NewSize.Width;
            decimal h = (decimal)e.NewSize.Height;
            panelDisplayHeight = h;
            panelDisplayWidth = w;
            _adorner.ParentHeight = (decimal)e.NewSize.Height;
            this.dividersCanvas.Children.Clear();
            btnNewItem.Visibility = System.Windows.Visibility.Collapsed;
            _timerOpen.Stop();
            _timerClose.Stop();
            bool isHourLine = true;
            for (decimal i = (h / 24); i <h; i += (h / 24))
            {

                var hourLine = new Line
                {
                    Stroke = new SolidColorBrush(Color.FromArgb(255,100,100,100)),
                    X1 = 0,
                    Y1 = (double)i,
                    X2 = (double)w,
                    Y2 = (double)i
                };
               
                hourLine.StrokeThickness = 1;

                this.dividersCanvas.Children.Add(hourLine);
            }


            for (decimal i = (h / 48); i < h; i += (h / 24))
            {

                var hourLine = new Line
                {
                    Stroke = new SolidColorBrush(Color.FromArgb(255, 100, 100, 100)),
                    X1 = 0,
                    Y1 = (double)i,
                    X2 = (double)w,
                    Y2 = (double)i
                };

                hourLine.StrokeThickness = 0.5;

                this.dividersCanvas.Children.Add(hourLine);
            }

            if (e.PreviousSize.Height != 0)
            {
                decimal ratio = (decimal)(e.NewSize.Height/e.PreviousSize.Height);

                
                _adorner.ParentRatio = (decimal)ratio;
                foreach (ScheduleItemControl scheduleItemControl in scheduleItems)
                {
                    AdornedObject adornedObject = (AdornedObject)scheduleItemControl.Tag;
                    adornedObject.Y = (double)(((decimal)adornedObject.Y) * ratio);
                    adornedObject.ObjectHeight = (double)(((decimal)adornedObject.ObjectHeight) * ratio);
                }

                _adorner.Y = (double)(((decimal)_adorner.Y) * ratio);
                _adorner.Height = (double)(((decimal)_adorner.Height) * ratio); 
            }
        }

        private void scheduleItem_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            ScheduleItemControl scheduleItemControl = (ScheduleItemControl)sender;
            if (!scheduleItemControl.IsInEditMode)
            {

                scheduleItemControl.ShowToolbar();
                Rect bounds = CalculateBoundry(scheduleItemControl);
                _adorner.SetBounds(bounds.X, bounds.Y, bounds.Width, bounds.Height);
                _adorner.StartMoveDrag();
                
            }
        }

       

        private void LayoutRoot_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            double aaa = e.NewSize.Height;  
        }


        public void AddScheduleItem(DateTime startTime,DateTime endTime,string description)
        {
//             <SchedulerControl:ScheduleItemControl x:Name="mainText1"  Height="100" MouseLeftButtonDown="Image_MouseLeftButtonDown" FontFamily="Tahoma" ScheduleDescription="اين يك آزمايش است براي فشسن 1">
//                </SchedulerControl:ScheduleItemControl>
            ScheduleItemControl scheduleItem = new ScheduleItemControl();
            Canvas.SetLeft(scheduleItem,0);
            Canvas.SetTop(scheduleItem, (double)DateTimeToHeight(startTime));
            scheduleItem.Height = (double)(DateTimeToHeight(endTime) - DateTimeToHeight(startTime));
            scheduleItem.ScheduleDescription = description;
            scheduleItem.MouseLeftButtonDown +=new MouseButtonEventHandler(scheduleItem_MouseLeftButtonDown);
            scheduleItem.MouseMove += new MouseEventHandler(scheduleItem_MouseMove);
            scheduleItem.MouseLeave += new MouseEventHandler(scheduleItem_MouseLeave);
            scheduleItem.Width = (double)_currentContainerWidth;
            AdornedObject adornedObject = new AdornedObject(scheduleItem, 0);
            scheduleItem.Margin = new Thickness(0);
            scheduleItem.Tag = adornedObject;


            if (IsInCollision(scheduleItem)) return;


            _adorner.AdornedObject = adornedObject;
            panelDisplay.Children.Add(scheduleItem);
            scheduleItems.Add(scheduleItem);


            _adorner.MetaData.StartTime = startTime;
            _adorner.MetaData.EndTime = endTime;
            
            ScheduleItemControl scheduleItemControl = (ScheduleItemControl)adornedObject.AdornedElement;
            _adorner.MetaData.ItemDate = scheduleItemControl.CurrentViewDate;


            

        }

        void scheduleItem_MouseLeave(object sender, MouseEventArgs e)
        {
            //_adorner.HideToolbar();
        }

        
		
		
		public ScheduleItemControl AddScheduleItem(decimal startY,decimal endY,string description)
        {
//             <SchedulerControl:ScheduleItemControl x:Name="mainText1"  Height="100" MouseLeftButtonDown="Image_MouseLeftButtonDown" FontFamily="Tahoma" ScheduleDescription="اين يك آزمايش است براي فشسن 1">
//                </SchedulerControl:ScheduleItemControl>
            ScheduleItemControl scheduleItem = new ScheduleItemControl();
		    scheduleItem.CurrentViewDate = this.CurrentViewDate; 
            Canvas.SetLeft(scheduleItem,0);
            Canvas.SetTop(scheduleItem, (double)startY);
            scheduleItem.Height = (double)(endY - startY);
            scheduleItem.ScheduleDescription = description;
            scheduleItem.MouseLeftButtonDown +=new MouseButtonEventHandler(scheduleItem_MouseLeftButtonDown);
            scheduleItem.MouseEnter += new MouseEventHandler(scheduleItem_MouseEnter);
            scheduleItem.MouseMove += new MouseEventHandler(scheduleItem_MouseMove);
            scheduleItem.MouseLeave += new MouseEventHandler(scheduleItem_MouseLeave);
            scheduleItem.Width = (double)_currentContainerWidth;
            AdornedObject adornedObject = new AdornedObject(scheduleItem, 0);
            scheduleItem.Margin = new Thickness(0);
            scheduleItem.Tag = adornedObject;

            if (IsInCollision(scheduleItem)) return null;

            panelDisplay.Children.Add(scheduleItem);
            scheduleItems.Add(scheduleItem);
		    
            _adorner.AdornedObject = adornedObject;
            _adorner.MetaData.StartTime = HeightToDateTime(startY);
            _adorner.MetaData.EndTime = HeightToDateTime(endY);
          

            ScheduleItemControl scheduleItemControl = (ScheduleItemControl)adornedObject.AdornedElement;
            _adorner.MetaData.ItemDate = scheduleItemControl.CurrentViewDate; 

			return scheduleItem;
        }

        void scheduleItem_MouseEnter(object sender, MouseEventArgs e)
        {
//            ScheduleItemControl scheduleItemControl = (ScheduleItemControl) sender;
//            if (!scheduleItemControl.IsInEditMode)
//            {
//                double parentWidth = panelDisplay.DesiredSize.Width;
//                scheduleItemControl.ShowToolbar();
//
//                panelDisplay.Children.Remove(scheduleItemControl);
//                panelDisplay.Children.Insert(0, scheduleItemControl);
//
//                _adorner.SetAdornedObject((IAdornedObject) scheduleItemControl.Tag);
//                _adorner.SetAdornerFrame(frame3);
//                
//                Rect bounds = CalculateBoundry(scheduleItemControl);
//                _adorner.SetBounds(bounds.X, bounds.Y, bounds.Width, bounds.Height);
//                
//            }

        }

        void scheduleItem_MouseMove(object sender, MouseEventArgs e)
        {
            ScheduleItemControl scheduleItemControl = (ScheduleItemControl)sender;
            if (!scheduleItemControl.IsInEditMode)
            {
                double parentWidth = panelDisplay.DesiredSize.Width;
                scheduleItemControl.ShowToolbar();

                panelDisplay.Children.Remove(scheduleItemControl);
                panelDisplay.Children.Insert(0, scheduleItemControl);

                _adorner.SetAdornedObject((IAdornedObject)scheduleItemControl.Tag);
                _adorner.SetAdornerFrame(frame3);
                //_adorner.ShowToolbar();

                //Rect bounds = CalculateBoundry(scheduleItemControl);
                //_adorner.SetBounds(bounds.X, bounds.Y, bounds.Width, bounds.Height);

            }
        }


        private decimal DateTimeToHeight(DateTime dateTime)
        {
            int hour = dateTime.Hour;
            int minute = dateTime.Minute;
            decimal oneMinuteHeight = panelDisplayHeight/(24*60);
            decimal timeHeight = oneMinuteHeight*((hour*60) + minute);
            
            return timeHeight;
        }


        private DateTime HeightToDateTime(decimal height)
        {
            decimal oneMinuteHeight = panelDisplayHeight / (24 * 60);
            decimal minuteCount = height/oneMinuteHeight;
            int hour = (int)(minuteCount / 60);
            int minute = (int)(minuteCount % 60);
            DateTime dateTime = new DateTime(CurrentViewDate.Year, CurrentViewDate.Month, CurrentViewDate.Day, hour, minute, 0);
            return dateTime;
        }

        private ScheduleItemWindow window;
        void _adorner_Maximized(object sender)
        {
            window = new ScheduleItemWindow();
            window.Closed +=new EventHandler(window_Closed);
            window.MetaData = _adorner.MetaData;  
		    window.Show();
        }

        void window_Closed(object sender, EventArgs e)
        {
            if(window.DialogResult == true)
            {
                _adorner.MetaData = window.MetaData;
                decimal _cY1 = DateTimeToHeight(window.MetaData.StartTime);
                decimal _cY2 = DateTimeToHeight(window.MetaData.EndTime);
                decimal _cH = _cY2 - _cY1;
                _adorner.Y = (double)_cY1;
                _adorner.Height = (double)_cH;
                _adorner.AdornedObject.Y = (double)_cY1;
                _adorner.AdornedObject.ObjectHeight = (double)_cH;
                
                _adorner.trTranslate.Y = (double)_cY1;
                var adornedObject = (AdornedObject)_adorner.AdornedObject;
                ScheduleItemControl scheduleItemControl = (ScheduleItemControl)adornedObject.AdornedElement;
                scheduleItemControl.ScheduleDescription = window.tbSubject.Text;  
            }
        }

        void _adorner_Closed(object sender)
        {
            foreach (ScheduleItemControl sic in scheduleItems)
            {
                sic.IsEnabled = true;
            }


            var adornedObject = (AdornedObject)_adorner.AdornedObject;
            ScheduleItemControl scheduleItemControl = (ScheduleItemControl)adornedObject.AdornedElement;
            panelDisplay.Children.Remove(scheduleItemControl);
            scheduleItems.Remove(scheduleItemControl);
            _adorner.Width = 0;
            _adorner.Height = 0;
            
        }

        void _adorner_Edited(object sender)
        {

            _adorner_Edited();
        }


        void _adorner_Edited()
        {



            var adornedObject = (AdornedObject)_adorner.AdornedObject;
            ScheduleItemControl scheduleItemControl = (ScheduleItemControl)adornedObject.AdornedElement;
            if (!scheduleItemControl.IsInEditMode)
            {
                scheduleItemControl.SwitchToEdit();
                scheduleItemControl.IsInEditMode = true;
                _currentEditingItem = scheduleItemControl;

                foreach (ScheduleItemControl sic in scheduleItems)
                {
                    if (sic != scheduleItemControl)
                    {
                        sic.IsEnabled = false;
                    }
                }
                IsInEditMode = true;

            }
            else
            {
                scheduleItemControl.SwitchToView();
                scheduleItemControl.IsInEditMode = false;
                foreach (ScheduleItemControl sic in scheduleItems)
                {
                    if (sic != scheduleItemControl)
                    {
                        sic.IsEnabled = true;
                    }
                }
                IsInEditMode = false;
            }
        }


        private decimal newMouseHeight;
        private decimal halfHourHeight;

        private void dividersCanvas_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            if (!IsInEditMode)
            {
                
                
                _timerOpen.Stop();
                _timerOpen.Start();
                
                newMouseHeight = (decimal) e.GetPosition(newItemCanvas).Y;
                halfHourHeight = panelDisplayHeight/48;
                newMouseHeight = newMouseHeight - (newMouseHeight%halfHourHeight);
                
                //Canvas.SetLeft(btnNewItem, (double) (panelDisplayWidth - (decimal) btnNewItem.Width));
                btnNewItem.Height = (double) halfHourHeight*2;
                btnNewItem.Width = (double)panelDisplayWidth;
                
            }
        }

        private void btnNewItem_Click(object sender, System.Windows.RoutedEventArgs e)
        {
			decimal left = (decimal)Canvas.GetLeft(btnNewItem);
			decimal top = (decimal)Canvas.GetTop(btnNewItem);
			decimal height = (decimal)btnNewItem.Height; 
			
        	ScheduleItemControl scheduleItem = AddScheduleItem(top, top + height, "");
			//scheduleItem.IsInEditMode = true;
			
			
        }

        private void panelDisplay_MouseLeave(object sender, MouseEventArgs e)
        {
            btnNewItem.Visibility = System.Windows.Visibility.Collapsed;
            _timerOpen.Stop();
            _timerClose.Stop(); 
        }

        private void newItemCanvas_MouseLeave(object sender, MouseEventArgs e)
        {
            btnNewItem.Visibility = System.Windows.Visibility.Collapsed;
            _timerOpen.Stop();
            _timerClose.Stop();
        }

        private Rect CalculateBoundry(ScheduleItemControl scheduleItemControl)
        {
            ScheduleItemControl _topScheduleItemControl = null;
            ScheduleItemControl _bottomScheduleItemControl = null;
            decimal _yDifferenceNew1 = 0;
            decimal _yDifferenceOld1 = 0;
            decimal _yDifferenceNew2 = 0;
            decimal _yDifferenceOld2 = 0;

            foreach (ScheduleItemControl sic in scheduleItems)
            {
                if(Canvas.GetTop(sic)+sic.Height <= Canvas.GetTop(scheduleItemControl))
                {
                    _yDifferenceNew1 = (decimal)(Canvas.GetTop(scheduleItemControl) - (Canvas.GetTop(sic) + sic.Height));

                    if (_yDifferenceOld1 == 0 || _yDifferenceNew1 <= _yDifferenceOld1)
                    {
                        _topScheduleItemControl = sic;
                        _yDifferenceOld1 = _yDifferenceNew1;
                    }
                }

                if (Canvas.GetTop(scheduleItemControl) + scheduleItemControl.Height <= Canvas.GetTop(sic))
                {
                    _yDifferenceNew2 = (decimal)(Canvas.GetTop(sic) - (Canvas.GetTop(scheduleItemControl) + scheduleItemControl.Height));

                    if (_yDifferenceOld2 == 0 || _yDifferenceNew2 <= _yDifferenceOld2)
                    {
                        _bottomScheduleItemControl = sic;
                        _yDifferenceOld2 = _yDifferenceNew2;
                    }
                }
            }

            decimal _topBoundry = 0;
            decimal _bottomBoundry = _currentContainerHeight;

            if(_topScheduleItemControl != null)
            {
                _topBoundry = (decimal)(Canvas.GetTop(_topScheduleItemControl) + _topScheduleItemControl.Height);
            }

            if (_bottomScheduleItemControl != null)
            {
                _bottomBoundry = (decimal)(Canvas.GetTop(_bottomScheduleItemControl));
            }

            Rect rect = new Rect(0, (double)_topBoundry, (double)_currentContainerWidth, (double)(_bottomBoundry - _topBoundry));
            scheduleItemControl.MoveBoundry = rect;

            return rect;
        }


        private bool IsInCollision(ScheduleItemControl scheduleItemControl)
        {
            decimal _newItemTop = (decimal)Canvas.GetTop(scheduleItemControl);
            decimal _newItemBottom = (decimal) (Canvas.GetTop(scheduleItemControl) + scheduleItemControl.Height);

            decimal _tempItemTop = 0;
            decimal _tempItemBottom = 0;


            foreach (ScheduleItemControl sic in scheduleItems)
            {
                _tempItemTop = (decimal)Canvas.GetTop(sic);
                _tempItemBottom = (decimal)(Canvas.GetTop(sic) + sic.Height);

                if (_newItemTop > _tempItemTop      &&  _newItemTop <    _tempItemBottom)    return true;
                if (_newItemBottom > _tempItemTop && _newItemBottom < _tempItemBottom)       return true;
            }

            return false;

            
        }

    }
}

